package com.ubao.ui.pullToRefreshListView;

import java.lang.reflect.Field;

import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.ubao.R;
import com.ubao.activity.MyApp;


public class NewsPullToRefreshListView_circle extends ListView implements OnScrollListener, PullToRefreshCallBack {
	private boolean mIsRequesting = false;

	private static final int TAP_TO_REFRESH = 1;
	private static final int PULL_TO_REFRESH = 2;
	private static final int RELEASE_TO_REFRESH = 3;
	private static final int REFRESHING = 4;

	private static final String TAG = "PullToRefreshListView";

	private NewsRefreshListener mOnRefreshListener;

	/**
	 * Listener that will receive notifications every time the list scrolls.
	 */
	private OnScrollListener mOnScrollListener;
	private LayoutInflater mInflater;

	private RelativeLayout mRefreshView;
	private TextView mRefreshViewText;
	private ImageView mRefreshViewImage;
	private ProgressBar mRefreshViewProgress;
	private TextView mRefreshViewLastUpdated;

	private RelativeLayout mRefreshView2;
	private ProgressBar mRefreshViewProgress2;

	private int mCurrentScrollState;
	private int mRefreshState;

	private RotateAnimation mFlipAnimation;
	private RotateAnimation mReverseFlipAnimation;

	private int mRefreshViewHeight;
	private int mRefreshOriginalTopPadding;
	private int mLastMotionY;

	private boolean mBounceHack;

	private boolean BottomFresh = false;

	public NewsPullToRefreshListView_circle(Context context) {
		super(context);
		init(context);
	}

	public NewsPullToRefreshListView_circle(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public NewsPullToRefreshListView_circle(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	private void init(Context context) {
		// Load all of the animations we need in code rather than through XML
		mFlipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		mFlipAnimation.setInterpolator(new LinearInterpolator());
		mFlipAnimation.setDuration(250);
		mFlipAnimation.setFillAfter(true);
		mReverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
		mReverseFlipAnimation.setDuration(250);
		mReverseFlipAnimation.setFillAfter(true);

		mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

		mRefreshView = (RelativeLayout) mInflater.inflate(R.layout.pull_to_refresh_header, this, false);
		mRefreshViewText = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
		mRefreshViewImage = (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
		mRefreshViewProgress = (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
		mRefreshViewLastUpdated = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);

		mRefreshViewImage.setMinimumHeight(50);
		mRefreshView.setOnClickListener(new OnClickRefreshListener());
		mRefreshOriginalTopPadding = 50;

		mRefreshState = TAP_TO_REFRESH;

		// addHeaderView(mRefreshView);

		mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

		mRefreshView2 = (RelativeLayout) mInflater.inflate(R.layout.pull_to_refresh_footer, this, false);

		mRefreshViewProgress2 = (ProgressBar) mRefreshView2.findViewById(R.id.pull_to_refresh_progress);
		mRefreshViewProgress2.setVisibility(View.VISIBLE);

		super.setOnScrollListener(this);

		measureView(mRefreshView);
		mRefreshViewHeight = mRefreshView.getMeasuredHeight();
	}

	@Override
	protected void onAttachedToWindow() {
		setSelection(getHeaderViewsCount());

		try {
			Class<?> c = Class.forName("android.os.Build$VERSION");
			Field field = c.getField("SDK_INT");
			final int sdk = (Integer) field.get(c);
			if (sdk > 15) {
				super.onAttachedToWindow();
			}
		} catch (Exception e) {
		}
	}

	@Override
	public void setAdapter(ListAdapter adapter) {
		try {
			Class<?> c = Class.forName("android.os.Build$VERSION");
			Field field = c.getField("SDK_INT");
			final int sdk = (Integer) field.get(c);
			if (sdk < 15) {
				if (getHeaderViewsCount() == 0) {
					addHeaderView(mRefreshView);
				}
			}
		} catch (Exception e) {
			if (getHeaderViewsCount() == 0) {
				addHeaderView(mRefreshView);
			}
		}
		super.setAdapter(adapter);
		Log.e("tag1", "setAdapter");
		setSelection(1);
	}

	/**
	 * Set the listener that will receive notifications every time the list
	 * scrolls.
	 * 
	 * @param l
	 *            The scroll listener.
	 */
	@Override
	public void setOnScrollListener(AbsListView.OnScrollListener l) {
		mOnScrollListener = l;
	}

	/**
	 * Register a callback to be invoked when this list should be refreshed.
	 * 
	 * @param onRefreshListener
	 *            The callback to run.
	 */
	@Override
	public void setOnRefreshListener(NewsRefreshListener onRefreshListener) {
		mOnRefreshListener = onRefreshListener;
	}

	/**
	 * Set a text to represent when the list was last updated.
	 * 
	 * @param lastUpdated
	 *            Last updated at.
	 */
	public void setLastUpdated(CharSequence lastUpdated) {
		log("xxxxxxx", "setLastUpdated");
		if (lastUpdated != null) {
			mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
			mRefreshViewLastUpdated.setText(lastUpdated);
		} else {
			mRefreshViewLastUpdated.setVisibility(View.GONE);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		final int y = (int) event.getY();
		mBounceHack = false;

		switch (event.getAction()) {
		case MotionEvent.ACTION_UP:
			log("xxxxxxx", "ACTION_UP");
			if (!isVerticalScrollBarEnabled()) {
				setVerticalScrollBarEnabled(true);
			}
			if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
				if (mRefreshView.getBottom() >= mRefreshViewHeight && mRefreshState == RELEASE_TO_REFRESH) {
					// Initiate the refresh
					log(TAG, "1111");
					mRefreshState = REFRESHING;
					prepareForRefresh();
					onRefresh();
				} else if (mRefreshView.getBottom() < mRefreshViewHeight * 2) {
					// Abort refresh and scroll down below the refresh view
					resetHeader();
					log(TAG, "2222");
					setSelection(1);
				}
			}
			break;
		case MotionEvent.ACTION_DOWN:
			log("xxxxxxx", "ACTION_DOWN");
			mLastMotionY = y;
			break;
		case MotionEvent.ACTION_MOVE:
			if (event.getY() < mLastMotionY && BottomFresh == false) {
				if (mCurrentPage < MyApp.MAX_PAGE) {
					BottomFresh = true;
					prepareForRefreshBottom();
				}
			} else

			if (applyHeaderPadding(event)) {

				return true;
			}
			;
			break;
		}

		return super.onTouchEvent(event);
	}

	private boolean applyHeaderPadding(MotionEvent ev) {
		// getHistorySize has been available since API 1
		int pointerCount = ev.getHistorySize();
		float pointer = ev.getY();
		// for (int p = 0; p < pointerCount; p++) {
		if (mRefreshState == RELEASE_TO_REFRESH) {
			if (isVerticalFadingEdgeEnabled()) {
				setVerticalScrollBarEnabled(false);
			}

			int historicalY = (int) pointer;// (int) ev.getHistoricalY(p);

			// Calculate the padding to apply, we divide by 1.7 to
			// simulate a more resistant effect during pull.
			int topPadding = (int) (((historicalY - mLastMotionY) - mRefreshViewHeight) / 2.7);
			log("padding ", "" + topPadding);
			if (topPadding <= 0 && mRefreshView.getPaddingTop() == 0) {

				return false;
			} else if (topPadding <= 0 && mRefreshView.getPaddingTop() != 0) {
				mRefreshView.setPadding(mRefreshView.getPaddingLeft(), 0, mRefreshView.getPaddingRight(), mRefreshView.getPaddingBottom());
				ev.setAction(MotionEvent.ACTION_UP);
				super.onTouchEvent(ev);
				ev.setAction(MotionEvent.ACTION_DOWN);
				// super.onTouchEvent(ev);
				return false;
			} else {
				mRefreshView.setPadding(mRefreshView.getPaddingLeft(), topPadding, mRefreshView.getPaddingRight(), mRefreshView.getPaddingBottom());
			}
			// }
			return true;
		}
		return false;
	}

	/**
	 * Sets the header padding back to original size.
	 */
	private void resetHeaderPadding() {
		log("resetHeaderPadding", "resetHeaderPadding1");
		mRefreshView.setPadding(mRefreshView.getPaddingLeft(), mRefreshOriginalTopPadding / 2, mRefreshView.getPaddingRight(), 0);
	}

	/**
	 * Resets the header to the original state.
	 */
	public void resetHeader() {
		log("xxxxxxx", "resetHeader");
		if (mRefreshState != TAP_TO_REFRESH) {
			mRefreshState = TAP_TO_REFRESH;

			resetHeaderPadding();

			// Set refresh view text to the pull label
			mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
			// Replace refresh drawable with arrow drawable
			mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);
			// Clear the full rotation animation
			mRefreshViewImage.clearAnimation();
			// Hide progress bar and arrow.
			mRefreshViewImage.setVisibility(View.INVISIBLE);
			mRefreshViewProgress.setVisibility(View.INVISIBLE);
		}
	}

	/**
	 * Resets the header to the original state.
	 */
	private void resetFooter() {
		log("xxxxxxx", "resetHeader");

		if (getFooterViewsCount() > 0) {
			try {
				removeFooterView(mRefreshView2);
			} catch (Exception e) {
			}
		}
		BottomFresh = false;
		// mRefreshViewProgress2.setVisibility(View.GONE);
	}

	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
		}

		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		// When the refresh view is completely visible, change the text to say
		// "Release to refresh..." and flip the arrow drawable.
		log("xxxxxxx", "onScroll");
		if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL && mRefreshState != REFRESHING) {
			if (firstVisibleItem == 0) {
				log("xxxxxxx", "onScrollxxxxxxxxxxxxxxxx");
				mRefreshViewImage.setVisibility(View.VISIBLE);
				if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20 || mRefreshView.getTop() >= 0) && mRefreshState != RELEASE_TO_REFRESH) {
					mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
					mRefreshView.setPadding(mRefreshView.getPaddingLeft(), mRefreshOriginalTopPadding, mRefreshView.getPaddingRight(), 0);
					mRefreshViewImage.clearAnimation();
					mRefreshViewImage.startAnimation(mFlipAnimation);
					mRefreshState = RELEASE_TO_REFRESH;
				}
			} else {
				mRefreshViewImage.setVisibility(View.GONE);
				resetHeader();
			}
		} else if (mCurrentScrollState == SCROLL_STATE_FLING && firstVisibleItem == 0 && mRefreshState != REFRESHING) {
			Log.e("tag1", "onScroll1");
			setSelection(1);
			mBounceHack = true;
		} else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
			Log.e("tag1", "onScroll2");
			setSelection(1);
		}

		if (mOnScrollListener != null) {
			mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
		}
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		if (scrollState == SCROLL_STATE_TOUCH_SCROLL && getHeaderViewsCount() == 0) {
			try {
				Class<?> c = Class.forName("android.os.Build$VERSION");
				Field field = c.getField("SDK_INT");
				final int sdk = (Integer) field.get(c);
				if (sdk >= 15) {
					ListAdapter adapter = getAdapter();
					setAdapter(null);
					addHeaderView(mRefreshView);
					setAdapter(adapter);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		mCurrentScrollState = scrollState;
		log("xxxxxxx", "onScrollStateChanged " + this.getLastVisiblePosition() + "  " + this.getCount() + " " + BottomFresh);
		if (mCurrentScrollState == SCROLL_STATE_IDLE) {
			mBounceHack = false;
		}

		if (this.getLastVisiblePosition() == this.getCount() - 1 && BottomFresh == true) {
			onGetDown();
		}

		if (mOnScrollListener != null) {
			mOnScrollListener.onScrollStateChanged(view, scrollState);
		}
	}

	public void prepareForRefresh() {
		log("xxxxxxx", "prepareForRefresh");
		resetHeaderPadding();
		mRefreshViewImage.setVisibility(View.INVISIBLE);
		// We need this hack, otherwise it will keep the previous drawable.
		mRefreshViewImage.setImageDrawable(null);
		mRefreshViewProgress.setVisibility(View.VISIBLE);

		// Set refresh view text to the refreshing label
		mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);
		mRefreshState = REFRESHING;
	}

	public void prepareForRefreshBottom() {
		log("xxxxxxx", "prepareForRefreshBottom");
		if (getFooterViewsCount() == 0 && getAdapter() != null)
			addFooterView(mRefreshView2);
	}

	public void onRefresh() {
		log(TAG, "onRefresh");

		if (mOnRefreshListener != null) {
			mOnRefreshListener.onRefresh();
		}
	}

	public void onGetDown() {
		log(TAG, "onGetDown");
		if (!mIsRequesting) {
			if (mOnRefreshListener != null) {
				mIsRequesting = true;
				resetHeader();
				mOnRefreshListener.onGetDown();
			}
		}
	}

	/**
	 * Resets the list to a normal state after a refresh.
	 * 
	 * @param lastUpdated
	 *            Last updated at.
	 */
	@Override
	public void onRefreshComplete(CharSequence lastUpdated, int upDown) {
		setLastUpdated(lastUpdated);
		onRefreshComplete(upDown);
	}

	/**
	 * Resets the list to a normal state after a refresh.
	 */

	public void onRefreshComplete(int upDown) {
		mIsRequesting = false;
		Rect r = new Rect();
		mRefreshView.getChildVisibleRect(mRefreshViewProgress, r, new Point());
		log(TAG, "onRefreshComplete" + r.bottom);

		resetHeader();
		resetFooter();
		// removeHeaderView(mRefreshView);
		// mRefreshView.scrollTo(0, -60);
		// If refresh view is visible when loading completes, scroll down to
		// the next item.

		if (upDown != 1) {
			setSelection(getHeaderViewsCount());
		}
	}

	@Override
	public void setSelection(int a) {
		log("xxxxxxx", "setSelection");
		super.setSelection(a);
	}

	/**
	 * Invoked when the refresh view is clicked on. This is mainly used when
	 * there's only a few items in the list and it's not possible to drag the
	 * list.
	 */
	private class OnClickRefreshListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			if (mRefreshState != REFRESHING) {
				prepareForRefresh();
				onRefresh();
			}
		}

	}

	private boolean DEBUG = false;

	private void log(String tag, String msg) {
		if (DEBUG) {
			Log.d(tag, msg);
		}
	}

	public void refresh() {
		prepareForRefresh();
		Log.e("tag1", "refresh");
		setSelection(0);
	}

	public void reset() {
		resetHeader();
		resetFooter();
	}

	public void setAAdapter(ListAdapter adapter) {
		super.setAdapter(null);
		removeHeaderFooter();
		super.setAdapter(adapter);
	}

	public void removeHeaderFooter() {
		if (getHeaderViewsCount() == 1) {
			removeHeaderView(mRefreshView);
		}
		if (getFooterViewsCount() == 1) {
			removeFooterView(mRefreshView2);
		}
	}

	public void setFooterHeight(int height) {
		android.view.ViewGroup.LayoutParams params = mRefreshView2.getLayoutParams();
		params.height = height;
		mRefreshView2.setLayoutParams(params);
	}

	private int mCurrentPage = 0;

	public void setCurrentPage(int currentPage) {
		mCurrentPage = currentPage;
	}
}
